package com.uinnova.product.eam.init.expose;

import com.binary.core.exception.BinaryException;
import com.uinnova.project.base.diagram.exception.LoginFailException;
import com.uino.util.digest.impl.type.Md5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@WebFilter(urlPatterns = "/*")
@Component
@Order(2)
@Slf4j
public class ExposeMethodFilter implements Filter {

    private static final List<String> EAM_EXPOSE_TO_CMDB_URLS;

    @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

    @Value("${cmdb.eams.key:}")
    private String cmdbEamsKey;

    @Value("${cmdb.eams.secret:}")
    private String cmdbEamsSecret;

    static {
        EAM_EXPOSE_TO_CMDB_URLS = Stream.of(
                ""
        ).collect(Collectors.toList());
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 获取当前请求url
        String requestUri = request.getRequestURI();

        if (!EAM_EXPOSE_TO_CMDB_URLS.contains(requestUri)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        //暴漏给业务系统接口鉴权
        String sign = request.getParameter("sign");
        String ts = request.getParameter("ts");
        if (StringUtils.isBlank(sign) || StringUtils.isBlank(ts)) {
            resolver.resolveException(request,response,null,new LoginFailException("ts或sign不可为空"));
            return;
        }
        Date date;
        try {
            date = new Date(Long.parseLong(ts));
        } catch (Exception e) {
            resolver.resolveException(request,response,null,new LoginFailException("ts格式错误"));
            return;
        }
        Date afterDate = DateUtils.addMinutes(date, 20);
        Date beforeDate = DateUtils.addMinutes(date, -20);
        if (afterDate.getTime() < new Date().getTime()
                || beforeDate.getTime() > new Date().getTime()) {
            resolver.resolveException(request,response,null,new LoginFailException("ts需在20分钟内"));
            return;
        }
        String eamsKey = getBusinessKey(requestUri);
        String eamsSecret = getBusinessSecret(requestUri);
        String signature = eamsKey + eamsSecret + ts;
        if (sign.equals(Md5Util.string2Md5(signature))) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        resolver.resolveException(request , response, null, new LoginFailException("认证失败"));
    }

    private String getBusinessKey(String requestUri) {
        if (EAM_EXPOSE_TO_CMDB_URLS.contains(requestUri)) {
            return cmdbEamsKey;
        }
        throw new BinaryException("不支持的业务系统");
    }

    private String getBusinessSecret(String requestUri) {
        if (EAM_EXPOSE_TO_CMDB_URLS.contains(requestUri)) {
            return cmdbEamsSecret;
        }
        throw new BinaryException("不支持的业务系统");
    }
}
